﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using iTFF.WPF.Model.GlobalHotKeys;
using System.Runtime.InteropServices;
using iTFF.WPF.View;
using System.ComponentModel;
using iTFF.WPF.ViewModel;
using iTFF.WinFormsWrappers;
using System.Windows.Threading;
using iTFF.WPF.Resources.Languages;
using System.Globalization;
using System.Threading;

namespace iTFF.WPF.CP
{
    /// <summary>
    /// This class regroups all possible action for the application
    /// </summary>
    class ControlPanel : ViewModelBase
    {

        #region Singleton

        private static ControlPanel _instance;
        public static ControlPanel Instance
        {
            get
            {
                if (_instance == null)
                    _instance = new ControlPanel();
                return _instance;
            }
        }

        #endregion

        #region Fields

        Window _mainWindowView;
        GlobalHotKeysControlPanel _hotKeysCP;
        iTunesControlPanel _iTunesCP;
        ArtworksControlPanel _artworksCP;
        ToasterControlPanel _toasterCP;
        LyricsControlPanel _lyricsCP;

        string _notifyIconText;
        string _balloonTipText;
        BalloonTipIcon _balloonTipIcon;
        string _balloonTipTitle;
        private CultureInfo[] _availableCultures;

        #endregion

        #region Constructor
        public ControlPanel()
        {
            NotifyIconText = "iTunes Fast Forward";
        }
        #endregion

        #region CPs Properties

        public GlobalHotKeysControlPanel GlobalHotKeysControlPanel
        {
            get
            {
                if (_hotKeysCP == null)
                {
                    _hotKeysCP = new GlobalHotKeysControlPanel(_mainWindowView);
                    _hotKeysCP.HotkeyPressed += OnHotKeyPressed;
                }
                return _hotKeysCP;
            }
        }

        /// <summary>
        /// Gets access to the iTunes Control Panel. The first call to this property will launch iTunes if it isn't yet.
        /// </summary>
        public iTunesControlPanel iTunesControlPanel
        {
            get
            {
                if (_iTunesCP == null)
                {
                    _iTunesCP = new iTunesControlPanel();
                    // bind the playing tracks change handler in order to update the notifyicontext
                    _iTunesCP.PlayerPlayed += PlayerPlayed;
                    _iTunesCP.PlayerStopped += PlayerStopped;
                }
                return _iTunesCP;
            }
        }

        /// <summary>
        /// Gets the Artworks Control Panel
        /// </summary>
        public ArtworksControlPanel ArtworksControlPanel
        {
            get
            {
                if (_artworksCP == null)
                    _artworksCP = new ArtworksControlPanel();
                return _artworksCP;
            }
        }

        /// <summary>
        /// Gets the Toaster Control Panel
        /// </summary>
        public ToasterControlPanel ToasterControlPanel
        {
            get
            {
                if (_toasterCP == null)
                    _toasterCP = new ToasterControlPanel();
                return _toasterCP;
            }
        }

        /// <summary>
        /// Gets the Lyrics Control Panel
        /// </summary>
        public LyricsControlPanel LyricsControlPanel
        {
            get
            {
                if (_lyricsCP == null)
                    _lyricsCP = new LyricsControlPanel();
                return _lyricsCP;
            }
        }

        #endregion

        #region Initialization

        /// <summary>
        /// Initializes the ControlPanel by referencing the main window. Usefull when 
        /// </summary>
        /// <param name="mainWindow"></param>
        public void Initialize(Window mainWindowView)
        {
            _mainWindowView = mainWindowView;
        }

        #endregion

        #region HotKeys Actions
        void OnHotKeyPressed(object sender, iTFF.WPF.Model.GlobalHotKeys.GlobalHotKeyPressedEventArgs e)
        {
            DoAction(e.HotKey);
        }

        /// <summary>
        /// Does an action on key pressed
        /// </summary>
        void DoAction(GlobalHotKey hk)
        {
            try
            {
                switch (hk.Name)
                {
                    case "VolumeUp":
                        iTunesControlPanel.Volume += 5;
                        break;
                    case "VolumeDown":
                        iTunesControlPanel.Volume -= 5;
                        break;
                    case "Mute":
                        iTunesControlPanel.ToggleMute();
                        break;
                    case "ToggleShuffle":
                        iTunesControlPanel.ToggleShuffle();
                        break;
                    case "ShowToast":
                        ToasterControlPanel.ShowToast();
                        break;
                    //case "ShowLyrics":
                    //    _form.LyricsDownloadAndApply(iTunesActions.Instance.PlayingTrack, false);
                    //    _form.LyricsShow();
                    //    break;
                    //case "SearchTags":
                    //    _form.MusicDNSSearchTagsForSelectedTrack();
                    //    break;
                    case "AddToPlaylist":
                        iTunesControlPanel.AddPlayingTrackToArtistNamePlaylist();
                        break;
                    case "SongRatingClear":
                        iTunesControlPanel.SongRate = 0;
                        break;
                    case "SongRating1":
                        iTunesControlPanel.SongRate = 1;
                        break;
                    case "SongRating2":
                        iTunesControlPanel.SongRate = 2;
                        break;
                    case "SongRating3":
                        iTunesControlPanel.SongRate = 3;
                        break;
                    case "SongRating4":
                        iTunesControlPanel.SongRate = 4;
                        break;
                    case "SongRating5":
                        iTunesControlPanel.SongRate = 5;
                        break;
                    default:
                        iTunesControlPanel.DoAction(hk.Name);
                        break;
                }
            }
            catch (ApplicationException ae)
            {
                // show the error into the balloon
                ShowBalloon(Strings.Error, BalloonTipIcon.Error, ae.Message);
            }

        }

        #endregion

        #region Main Window

        /// <summary>
        /// Shows the main window at foreground
        /// </summary>
        public void ShowMainWindow()
        {
            _mainWindowView.Activate();
        }

        /// <summary>
        /// The text displayed by the NotifyIcon
        /// </summary>
        public string NotifyIconText
        {
            get { return _notifyIconText; }
            set
            {
                if (_notifyIconText != value)
                {
                    _notifyIconText = value;
                    OnPropertyChanged("NotifyIconText");
                }
            }
        }

        /// <summary>
        /// The icon of the Ballon Tip Icon
        /// </summary>
        public BalloonTipIcon BalloonTipIcon
        {
            get { return _balloonTipIcon; }
            set
            {
                if (_balloonTipIcon != value)
                {
                    _balloonTipIcon = value;
                    OnPropertyChanged("BalloonTipIcon");
                }
            }
        }

        /// <summary>
        /// The balloon title
        /// </summary>
        public string BalloonTipTitle
        {
            get { return _balloonTipTitle; }
            set
            {
                if (_balloonTipTitle != value)
                {
                    _balloonTipTitle = value;
                    OnPropertyChanged("BalloonTipTitle");
                }
            }
        }

        /// <summary>
        /// The balloon content text
        /// </summary>
        public string BalloonTipText
        {
            get { return _balloonTipText; }
            set
            {
                if (_balloonTipText != value)
                {
                    _balloonTipText = value;
                    OnPropertyChanged("BalloonTipText");
                }
            }
        }

        /// <summary>
        /// Shows the NotifyIcon balloon
        /// </summary>
        /// <param name="balloonTipTitle"></param>
        /// <param name="balloonTipIcon"></param>
        /// <param name="notifyIconText"></param>
        public void ShowBalloon(string balloonTipTitle, BalloonTipIcon balloonTipIcon, string balloonTipText)
        {
            ShowBalloon(balloonTipTitle, balloonTipIcon, balloonTipText, 3000);
        }

        /// <summary>
        /// Shows the NotifyIcon balloon
        /// </summary>
        /// <param name="balloonTipTitle"></param>
        /// <param name="balloonTipIcon"></param>
        /// <param name="notifyIconText"></param>
        /// <param name="timeout">in milliseconds</param>
        public void ShowBalloon(string balloonTipTitle, BalloonTipIcon balloonTipIcon, string balloonTipText, int timeout)
        {
            BalloonTipTitle = balloonTipTitle;
            BalloonTipIcon = balloonTipIcon;
            BalloonTipText = balloonTipText;
            var not = _mainWindowView.FindName("notifyIcon") as NotifyIcon;
            if (not != null)
                not.ShowBalloonTip(timeout);
        }

        /// <summary>
        /// Returns the MainWindow dispatcher. Usefull when wanting to acces to the UI owner thread from ViewModel
        /// </summary>
        public Dispatcher MainWindowDispatcher
        {
            get { return _mainWindowView != null ? _mainWindowView.Dispatcher : null; }
        }

        /// <summary>
        /// Executes the lambda expression code with the ui code
        /// </summary>
        /// <param name="t"></param>
        public void ExecuteActionWithUIThread(Action t)
        {
            MainWindowDispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, t);
        }


        #endregion

        #region Show errors in ballon

        /// <summary>
        /// Shows an error in the balloon tooltip
        /// </summary>
        /// <param name="title"></param>
        /// <param name="text"></param>
        public void ShowError(Exception e)
        {
            ShowError(e.Message);
        }

        /// <summary>
        /// Shows an error in the balloon tooltip
        /// </summary>
        /// <param name="text"></param>
        public void ShowError(string text)
        {
            ShowBalloon(Strings.Error, BalloonTipIcon.Error, text);
        }

        /// <summary>
        /// Shows an error in the balloon tooltip
        /// </summary>
        /// <param name="text"></param>
        public void ShowError(string text, BalloonTipIcon icon)
        {
            ShowBalloon(Strings.Error, icon, text);
        }

        #endregion

        #region iTunes

        /// <summary>
        /// Updates the NotifyIconText
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void PlayerPlayed(object sender, iTFF.WPF.Model.iTunes.iTunesTrackEventArgs e)
        {
            UpdateNotifyIcon(e.Track);

            // shows the toast (if enable)
            // show it with the UI-Thread
            ExecuteActionWithUIThread(() => ToasterControlPanel.ShowToast());
        }

        /// <summary>
        /// Updates the NotifyIconText
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void PlayerStopped(object sender, iTFF.WPF.Model.iTunes.iTunesTrackEventArgs e)
        {
            UpdateNotifyIcon(null);
        }

        /// <summary>
        /// Updates the NotifyIcon text to display current playing track
        /// </summary>
        void UpdateNotifyIcon(iTunesLib.IITTrack track)
        {
            if (track != null)
            {
                var str = string.Format("iTFF{0}{1}{0}{2}{0}{3}", Environment.NewLine, track.Artist, track.Name, track.Album);
                if (str.Length > 63)
                    str = str.Substring(0, 63);

                NotifyIconText = str;
            }
            else
                NotifyIconText = "iTunes Fast Forward";
        }

        #endregion

        #region Application Sutdown

        /// <summary>
        /// Shutdowns the application, with the owner thread
        /// </summary>
        public void SutdownApplication()
        {
            _mainWindowView.Dispatcher.Invoke(DispatcherPriority.Normal, (Action)(() =>
            {
                App.Current.Shutdown();
            }));
        }

        #endregion

        #region Language support

        /// <summary>
        /// Gets the selected User culture or the default one. Sets the default culture too.
        /// </summary>
        public CultureInfo UserCultureInfo
        {
            get
            {
                if (string.IsNullOrEmpty(Settings.Default.UserLanguage))
                    return CultureInfo.CurrentCulture;
                else
                    return new CultureInfo(Settings.Default.UserLanguage);
            }
            set
            {
                if (value == null)
                {
                    Settings.Default.UserLanguage = null;
                    return;
                }

                if (Settings.Default.UserLanguage != value.IetfLanguageTag)
                    Settings.Default.UserLanguage = value.IetfLanguageTag;

                Thread.CurrentThread.CurrentCulture =
                    Thread.CurrentThread.CurrentUICulture =
                        new CultureInfo(value.IetfLanguageTag);
            }
        }

        /// <summary>
        /// Gets the list of available cultures
        /// </summary>
        public CultureInfo[] AvailableCultures
        {
            get
            {
                if (_availableCultures == null)
                    _availableCultures = new CultureInfo[] { new CultureInfo("fr-FR"), new CultureInfo("en-US") };
                return _availableCultures;
            }
        }

        #endregion

        #region SQL

        /// <summary>
        /// Gets the connection string for the SQL CE database (into the iTunes library folder)
        /// </summary>
        public string SQLCeDatabaseConnectionString
        {
            get { return string.Format(Settings.Default.SQLCeDatabaseConnectionString, iTunesControlPanel.iTunesLibraryFolderPath); }
        }

        #endregion

        #region Dispose

        protected override void OnDispose()
        {
            // dispose all sub control panel

            if (_hotKeysCP != null)
            {
                _hotKeysCP.Dispose();
                _hotKeysCP = null;
            }

            if (_iTunesCP != null)
            {
                _iTunesCP.Dispose();
                _iTunesCP = null;
            }

            if (_toasterCP != null)
            {
                _toasterCP.Dispose();
                _toasterCP = null;
            }

            _lyricsCP = null;
            _artworksCP = null;

        }

        #endregion

    }
}
